package fr.bludwarf.skywarrior.global;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import fr.bludwarf.skywarrior.exceptions.JoueurInconnuException;
import fr.bludwarf.skywarrior.ile.Ile;
import fr.bludwarf.skywarrior.joueur.Joueur;

public class Monde extends EntiteMere<Joueur> {
	
	public static final String LE_MONDE = "Le Monde";
	
	public static final Map<Integer, Monde> MONDES = new HashMap<Integer, Monde>();
	public int _idPartie;
	
	public final Map<String, Ile> iles = new HashMap<String, Ile>();

	public Monde(int idPartie)
	{
		super(null, String.format("%s #%s", LE_MONDE, idPartie));
		_idPartie = idPartie;
	}

	public void ajouterJoueur(String nomJoueur, String nomIle) throws JoueurInconnuException
	{
		final Joueur joueur = getJoueur(nomJoueur);
		final Ile ile = getIle(nomIle);
		ile.setJoueur(joueur);
		joueur.add(ile);
		add(joueur);
	}
	
	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder();

		sb.append("Monde :");
		
		for (final Joueur joueur : getJoueurs())
		{
			sb.append("\n\t").append(joueur);
		}

		return sb.toString();
	}
	
	public Joueur getJoueur(final String nom) throws JoueurInconnuException
	{
		for (final Joueur joueuri : getJoueurs())
		{
			if (joueuri.getNom().equals(nom))
				return joueuri;
		}
		
		// Ajout
		final Joueur joueur = new Joueur(this, nom);
		add(joueur);
		return joueur;
	}
	
	public Ile getIle(final String nom)
	{
		if (!iles.containsKey(nom))
		{
			iles.put(nom, new Ile(this, nom));
		}
		return iles.get(nom);
	}

	public Ile getSeuleIle() 
	{
		// On recherche l'ile parmis tous les joueurs
		final Set<Joueur> joueurs = getJoueurs();		
		if (joueurs.size() != 1)
		{
			throw new RuntimeException("Impossible de trouver la seule ile car il ne faut qu'un joueur");
		}
		
		for (final Joueur joueur : joueurs)
		{
			final Set<Ile> iles = joueur.getIles();
			if (iles.size() != 1)
			{
				throw new RuntimeException(String.format("Impossible de trouver la seule ile car %s a plusieurs iles", joueur.getNom()));
			}
			
			for (final Ile ile : iles)
				return ile;
		}
		
		throw new RuntimeException("Impossible de trouver la seule ile pour des raisons d'implémentation");
	}

	public Set<Joueur> getJoueurs() {
		return _fils;
	}

	public boolean contient(Joueur joueur)
	{
		return contient(joueur.getNom());
	}

	public boolean contient(String nom)
	{
		// incorrect car Set générique => uniquement manipulation d'Object
//		return getJoueurs().contains(joueur);
		for (final Joueur joueuri : getJoueurs())
		{
			if (joueuri.getNom().equals(nom))
				return true;
		}
		return false;
	}

	public static Monde getMonde(int idPartie)
	{
		if (!MONDES.containsKey(idPartie))
		{
			MONDES.put(idPartie, new Monde(idPartie));
		}
		return MONDES.get(idPartie);
	}
	
	@Override
	public Monde getMonde()
	{
		return this;
	}

}
